{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "40ab9c7e-95fe-4f80-ad43-5eba33477526",
   "metadata": {},
   "source": [
    "# 1.装饰器"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "760135ae-3b99-46cf-be1b-333b37d7e836",
   "metadata": {},
   "source": [
    "## 1.1装饰器定义"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "269b247b-b036-4d75-b985-dd071b783f3a",
   "metadata": {},
   "source": [
    "函数装饰器允许在源码中“标记”函数，以某种方式增强函数的行为。</br>\n",
    "装饰器是一种可调用对象，其参数是另一个函数（被装饰的函数）。</br>\n",
    "装饰器可能会对被装饰的函数做些处理，然后返回函数，或者把函数替换成另一个函数或可调用对象。</br>\n",
    "\n",
    "语法如下："
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ae3b136e-c994-4a0e-98bd-5137b062125f",
   "metadata": {},
   "source": [
    "装饰器使用符号@ <br>\n",
    "假如有一个名为decorate的装饰器：\n",
    "```python\n",
    "@decorate\n",
    "def target():\n",
    "    print('running target()')\n",
    "```\n",
    "那么上述代码的效果和下述写法一样：\n",
    "```python\n",
    "def target():\n",
    "    print('running target()')\n",
    "\n",
    "target = decorate(target)\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2c32fd56-a3e2-4059-9930-a898d529f39f",
   "metadata": {},
   "source": [
    "## 1.2例子：装饰器通常会把一个函数替换成另一个函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "653a7fdb-6386-427f-8d4b-965007ee2ac8",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "running inner()\n"
     ]
    }
   ],
   "source": [
    "#定义一个装饰器\n",
    "def deco(func):\n",
    "    #定义一个内部函数\n",
    "    def inner():\n",
    "        print('running inner()')\n",
    "    #返回内部函数\n",
    "    return inner\n",
    "\n",
    "#根据定义等效于 target = deco(target)\n",
    "@deco\n",
    "def target():\n",
    "    print('running target()')\n",
    "\n",
    "#等效于deco(target)()\n",
    "#deco(target)返回的是inner()函数的引用\n",
    "#最终调用的是inner()\n",
    "target()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "0bc95c51-59e5-40cd-a884-0f365fb3f97e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<function __main__.deco.<locals>.inner()>"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#查看下target的引用\n",
    "target"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fe557e3b-4eb6-43fd-8005-217170b23d17",
   "metadata": {},
   "source": [
    "可以看见target指向了deco函数的内部函数inner()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ed4cdff0-a21c-4c7a-b088-740494f77edc",
   "metadata": {},
   "source": [
    "## 1.3装饰器执行\n",
    "装饰器在被装饰的函数定义之后立即执行。在导入模块时(import)。</br>\n",
    "下面用一个注册用户的例子说明"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "74d0860e-4604-4482-b93b-fe9bfec784b2",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "running reg user(<function user1 at 0x000001C9254F6AC0>)\n",
      "running reg user(<function user3 at 0x000001C9254F6D40>)\n",
      "running main()\n",
      "user_list -> [<function user1 at 0x000001C9254F6AC0>, <function user3 at 0x000001C9254F6D40>]\n",
      "running user1()\n",
      "running user2()\n",
      "running user3()\n"
     ]
    }
   ],
   "source": [
    "#定义一个列表用来存储用户函数的引用\n",
    "user_list = []\n",
    "\n",
    "#定义装饰器函数此函式功能是增强被装饰的函数做一些额外操作，（记录被装饰函数的引用，并返回原函数）\n",
    "def reg_user(func):\n",
    "    print(f'running reg user({func})')\n",
    "    user_list.append(func)\n",
    "    return func\n",
    "\n",
    "@reg_user\n",
    "def user1():\n",
    "    print('running user1()')\n",
    "\n",
    "def user2():\n",
    "    print('running user2()')\n",
    "\n",
    "@reg_user\n",
    "def user3():\n",
    "    print('running user3()')\n",
    "\n",
    "def main():\n",
    "    print('running main()')\n",
    "    print('user_list ->', user_list)\n",
    "    user1()\n",
    "    user2()\n",
    "    user3()\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    main()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2bc7c24b-b7b4-4012-8490-d7115c4442e5",
   "metadata": {},
   "source": [
    "## 1.4总结\n",
    "1. 装饰器是一个函数或其它可调用对象。\n",
    "2. 装饰器可以把被装饰的函数替换成别的函数。\n",
    "3. 装饰器在加载模块（import）时立即执行。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cc7a6681-34fa-4aea-a02d-a11063bb96ec",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
